﻿//该控由datapager代替
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Water.Resources.Globalize;
using Water.Web;
using Water.Web.Controls.BaseInterface;
using System.Collections.Specialized;
using System.Text.RegularExpressions;

[assembly: WebResource("Water.Resources.Default.JS.Pager.Pager.js", "text/javascript")]
namespace Water.Web.Controls
{
    [Designer(typeof(Water.Web.Controls.Design.PagerControlDesigner))]
    [DefaultProperty("PageSize")]
    [DefaultEvent("PageChanged")]
    [ParseChildren(false)]
    [PersistChildren(true)]
    [ToolboxData("<{0}:Pager runat=server></{0}:Pager>")]
    [ToolboxItem(false)]
    public class Pager : Panel, INamingContainer, IPostBackEventHandler, IPostBackDataHandler, ICallBackable
    {
        #region Private fields
        private string inputPageIndex;
        private string currentUrl;
        private string queryString;

        private static readonly object EventPageChanging = new object();
        private static readonly object EventPageChanged = new object();
        bool pageChangeEventHandled = false;


        private string imagePath;
        private string submitButtonImageUrl;


        private bool isCallBack = true;
        private string displayDuringCallBackTextControls;

        //DataPager must be asp.net 3.5 or over
        private DataPager dataPager;
        #endregion

        #region Properties

        #region Navigation Buttons

        [Browsable(true), GlobalizeCategory("Navigation"), DefaultValue(false), GlobalizeDescription("ShowNavigationToolTip"), Themeable(true)]
        public bool ShowNavigationToolTip
        {
            get
            {
                object obj = ViewState["ShowNvToolTip"];
                return (obj == null) ? false : (bool)obj;
            }
            set
            {
                ViewState["ShowNvToolTip"] = value;
            }
        }

        [Browsable(true), Themeable(true), GlobalizeCategory("Navigation"), DefaultValue("go to {0}"), GlobalizeDescription("NavigationToolTipTextFormatString")]
        public string NavigationToolTipTextFormatString
        {
            get
            {
                object obj = ViewState["NvToolTipFormatString"];
                if (obj == null)
                {
                    if (ShowNavigationToolTip)
                        return "go to {0}";
                    return null;
                }
                return (string)obj;
            }
            set
            {
                string tip = value;
                if (tip.Trim().Length < 1 && tip.IndexOf("{0}") < 0)
                    tip = "{0}";
                ViewState["NvToolTipFormatString"] = tip;
            }
        }

        [Browsable(true), Themeable(true), DefaultValue(""), GlobalizeCategory("Navigation"), GlobalizeDescription("NBTFormatString")]
        public string NumericButtonTextFormatString
        {
            get
            {
                object obj = ViewState["NumericButtonTextFormatString"];
                return (obj == null) ? String.Empty : (string)obj;
            }
            set
            {
                ViewState["NumericButtonTextFormatString"] = value;
            }
        }

        [Browsable(true), Themeable(true), DefaultValue(""), GlobalizeCategory("Navigation"), GlobalizeDescription("CPBTextFormatString")]
        public string CurrentPageButtonTextFormatString
        {
            get
            {
                object obj = ViewState["CurrentPageButtonTextFormatString"];
                return (obj == null) ? NumericButtonTextFormatString : (string)obj;
            }
            set
            {
                ViewState["CurrentPageButtonTextFormatString"] = value;
            }
        }

        [Browsable(true), Themeable(true), DefaultValue(PagingButtonType.Image), GlobalizeCategory("Navigation"), GlobalizeDescription("PagingButtonType")]
        public PagingButtonType PagingButtonType
        {
            get
            {
                object obj = ViewState["PagingButtonType"];
                return (obj == null) ? PagingButtonType.Image : (PagingButtonType)obj;
            }
            set
            {
                ViewState["PagingButtonType"] = value;
            }
        }

        [Browsable(true), Themeable(true), DefaultValue(PagingButtonType.Text), GlobalizeCategory("Navigation"), GlobalizeDescription("NumericButtonType")]
        public PagingButtonType NumericButtonType
        {
            get
            {
                object obj = ViewState["NumericButtonType"];
                return (obj == null) ? PagingButtonType.Text : (PagingButtonType)obj;
            }
            set
            {
                ViewState["NumericButtonType"] = value;
            }
        }

        [Browsable(true), Themeable(true), DefaultValue(PagingButtonLayoutType.None), GlobalizeCategory("Navigation"), GlobalizeDescription("PagingButtonLayoutType")]
        public PagingButtonLayoutType PagingButtonLayoutType
        {
            get
            {
                object obj = ViewState["PagingButtonLayoutType"];
                return (obj == null) ? PagingButtonLayoutType.None : (PagingButtonLayoutType)obj;
            }
            set { ViewState["PagingButtonLayoutType"] = value; }
        }

        [Browsable(true), Themeable(true), DefaultValue(PagingButtonPosition.Fixed), GlobalizeCategory("Navigation"), GlobalizeDescription("CurrentPageButtonPosition")]
        public PagingButtonPosition CurrentPageButtonPosition
        {
            get
            {
                object obj = ViewState["CurrentPageButtonPosition"];
                return (obj == null) ? PagingButtonPosition.Fixed : (PagingButtonPosition)obj;
            }
            set { ViewState["CurrentPageButtonPosition"] = value; }
        }

        [Browsable(true), Themeable(true), GlobalizeCategory("Navigation"), DefaultValue(PagingButtonType.Text), GlobalizeDescription("NavigationButtonType")]
        public PagingButtonType NavigationButtonType
        {
            get
            {
                object obj = ViewState["NavigationButtonType"];
                return (obj == null) ? PagingButtonType : (PagingButtonType)obj;
            }
            set
            {
                ViewState["NavigationButtonType"] = value;
            }
        }

        [Browsable(true), Themeable(true), DefaultValue(""), TypeConverter(typeof(TargetConverter)), GlobalizeCategory("Navigation"), GlobalizeDescription("UrlPagingTarget")]
        public string UrlPagingTarget
        {
            get
            {
                return (string)ViewState["UrlPagingTarget"];
            }
            set
            {
                ViewState["UrlPagingTarget"] = value;
            }
        }

        [Browsable(true), Themeable(true), GlobalizeCategory("Navigation"), DefaultValue(PagingButtonType.Text), GlobalizeDescription("MoreButtonType")]
        public PagingButtonType MoreButtonType
        {
            get
            {
                object obj = ViewState["MoreButtonType"];
                return (obj == null) ? PagingButtonType.Text : (PagingButtonType)obj;
            }
            set
            {
                ViewState["MoreButtonType"] = value;
            }
        }

        [Browsable(true), Themeable(true), GlobalizeCategory("Navigation"), DefaultValue(typeof(Unit), "3px"), GlobalizeDescription("PagingButtonSpacing")]
        public Unit PagingButtonSpacing
        {
            get
            {
                object obj = ViewState["PagingButtonSpacing"];
                return (obj == null) ? Unit.Pixel(3) : (Unit.Parse(obj.ToString()));
            }
            set
            {
                ViewState["PagingButtonSpacing"] = value;
            }
        }

        [Browsable(true), Themeable(true), GlobalizeDescription("ShowFirstLast"), GlobalizeCategory("Navigation"), DefaultValue(true)]
        public bool ShowFirstLast
        {
            get
            {
                object obj = ViewState["ShowFirstLast"];
                return (obj == null) ? true : (bool)obj;
            }
            set { ViewState["ShowFirstLast"] = value; }
        }

        [Browsable(true), Themeable(true), GlobalizeDescription("ShowPrevNext"), GlobalizeCategory("Navigation"), DefaultValue(true)]
        public bool ShowPrevNext
        {
            get
            {
                object obj = ViewState["ShowPrevNext"];
                return (obj == null) ? true : (bool)obj;
            }
            set { ViewState["ShowPrevNext"] = value; }
        }

        [Browsable(true), Themeable(true), GlobalizeDescription("ShowPageIndex"), GlobalizeCategory("Navigation"), DefaultValue(true)]
        public bool ShowPageIndex
        {
            get
            {
                object obj = ViewState["ShowPageIndex"];
                return (obj == null) ? true : (bool)obj;
            }
            set { ViewState["ShowPageIndex"] = value; }
        }

        [Browsable(true), Themeable(true), GlobalizeDescription("FirstPageText"), GlobalizeCategory("Navigation"), DefaultValue("&lt;&lt;")]
        public string FirstPageText
        {
            get
            {
                object obj = ViewState["FirstPageText"];
                return (obj == null) ? "&lt;&lt;" : (string)obj;
            }
            set { ViewState["FirstPageText"] = value; }
        }

        [Browsable(true), Themeable(true), GlobalizeDescription("PrevPageText"), GlobalizeCategory("Navigation"), DefaultValue("&lt;")]
        public string PrevPageText
        {
            get
            {

                object obj = ViewState["PrevPageText"];
                return (obj == null) ? "&lt;" : (string)obj;
            }
            set { ViewState["PrevPageText"] = value; }
        }

        [Browsable(true), Themeable(true), GlobalizeDescription("NextPageText"), GlobalizeCategory("Navigation"), DefaultValue("&gt;")]
        public string NextPageText
        {
            get
            {
                object obj = ViewState["NextPageText"];
                return (obj == null) ? "&gt;" : (string)obj;
            }
            set { ViewState["NextPageText"] = value; }
        }

        [Browsable(true), Themeable(true), GlobalizeDescription("LastPageText"), GlobalizeCategory("Navigation"), DefaultValue("&gt;&gt;")]
        public string LastPageText
        {
            get
            {
                object obj = ViewState["LastPageText"];
                return (obj == null) ? "&gt;&gt;" : (string)obj;
            }
            set { ViewState["LastPageText"] = value; }
        }

        [Browsable(true), Themeable(true), GlobalizeDescription("NumericButtonCount"), GlobalizeCategory("Navigation"), DefaultValue(10)]
        public int NumericButtonCount
        {
            get
            {
                object obj = ViewState["NumericButtonCount"];
                return (obj == null) ? 10 : (int)obj;
            }
            set { ViewState["NumericButtonCount"] = value; }
        }

        [Browsable(true), Themeable(true), GlobalizeCategory("Navigation"), GlobalizeDescription("ShowDisabledButtons"), DefaultValue(true)]
        public bool ShowDisabledButtons
        {
            get
            {
                object obj = ViewState["ShowDisabledButtons"];
                return (obj == null) ? true : (bool)obj;
            }
            set
            {
                ViewState["ShowDisabledButtons"] = value;
            }
        }

        [Browsable(true), Themeable(true), GlobalizeCategory("Navigation"), GlobalizeDescription("ShowMoreButtons"), DefaultValue(true)]
        public bool ShowMoreButtons
        {
            get
            {
                object obj = ViewState["ShowMoreButtons"];
                return (obj == null) ? true : (bool)obj;
            }
            set
            {
                ViewState["ShowMoreButtons"] = value;
            }
        }

        [Browsable(true), Category("Appearance"), DefaultValue(HorizontalAlign.NotSet), GlobalizeDescription("NavigationSectionAlign")]
        public HorizontalAlign NavigationSectionAlign
        {
            get
            {
                object obj = ViewState["NavigationSectionAlign"];
                return (null == obj) ? HorizontalAlign.NotSet : (HorizontalAlign)obj;
            }
            set
            {
                ViewState["NavigationSectionAlign"] = value;
            }
        }

        //[Obsolete("use CurrentPageButtonPosition instead"), Browsable(false), Themeable(false), GlobalizeCategory("Behavior"), GlobalizeDescription("CenterCurrentPageButton"), DefaultValue(false)]
        //public bool CenterCurrentPageButton
        //{
        //    get
        //    {
        //        return CurrentPageButtonPosition == PagingButtonPosition.Center;
        //    }
        //    set
        //    {
        //        if (value)
        //            CurrentPageButtonPosition = PagingButtonPosition.Center;
        //    }
        //}

        #endregion

        #region Image Navigation Buttons


        [Browsable(false)]
        public string ImagePath
        {
            get
            {
                if (string.IsNullOrEmpty(this.imagePath))
                {
                    if (DesignMode)
                        this.imagePath = "/Resources/Default/Images/Pager/";
                    else
                        this.imagePath = Water.Web.Path.ResourcePath + "Images/Pager/";
                }
                if (this.imagePath != null)
                {
                    this.imagePath = ResolveUrl(this.imagePath);
                }
                return imagePath;
            }
            set
            {
                string imgPath = value.Trim().Replace("\\", "/");
                this.imagePath = (imgPath.EndsWith("/")) ? imgPath : imgPath + "/";
            }
        }

        [Browsable(true), Themeable(true), Category("Appearance"), DefaultValue(".gif"), GlobalizeDescription("ButtonImageExtension")]
        public string ButtonImageExtension
        {
            get
            {
                object obj = ViewState["ButtonImageExtension"];
                return (obj == null) ? ".gif" : (string)obj;
            }
            set
            {
                string ext = value.Trim();
                ViewState["ButtonImageExtension"] = (ext.StartsWith(".")) ? ext : ("." + ext);
            }
        }

        [Browsable(true), Themeable(true), DefaultValue(null), Category("Appearance"), GlobalizeDescription("ButtonImageNameExtension")]
        public string ButtonImageNameExtension
        {
            get
            {
                object obj = ViewState["ButtonImageNameExtension"];
                return (obj == null) ? null : (string)obj;
            }
            set
            {
                ViewState["ButtonImageNameExtension"] = value;
            }
        }

        [Browsable(true), Themeable(true), DefaultValue(null), Category("Appearance"), GlobalizeDescription("CpiButtonImageNameExtension")]
        public string CpiButtonImageNameExtension
        {
            get
            {
                object obj = ViewState["CpiButtonImageNameExtension"];
                return (obj == null) ? ButtonImageNameExtension : (string)obj;
            }
            set
            {
                ViewState["CpiButtonImageNameExtension"] = value;
            }
        }

        [Browsable(true), Themeable(true), DefaultValue("_dis"), Category("Appearance"), GlobalizeDescription("DisabledButtonImageNameExtension")]
        public string DisabledButtonImageNameExtension
        {
            get
            {
                object obj = ViewState["DisabledButtonImageNameExtension"];
                return (obj == null) ? /*ButtonImageNameExtension*/"_dis" : (string)obj;
            }
            set
            {
                ViewState["DisabledButtonImageNameExtension"] = value;
            }
        }

        [Browsable(true), GlobalizeDescription("ButtonImageAlign"), DefaultValue(ImageAlign.NotSet), Category("Appearance")]
        public ImageAlign ButtonImageAlign
        {
            get
            {
                object obj = ViewState["ButtonImageAlign"];
                return (obj == null) ? ImageAlign.NotSet : (ImageAlign)obj;
            }
            set
            {
                if (value != ImageAlign.Right && value != ImageAlign.Left)
                    ViewState["ButtonImageAlign"] = value;
            }
        }


        #endregion

        #region Paging

        [Browsable(true), GlobalizeCategory("Paging"), DefaultValue(false), GlobalizeDescription("PagedControlID")]
        public virtual string PagedControlID
        {
            get
            {
                object obj2 = this.ViewState["PagedControlID"];
                if (obj2 != null)
                {
                    return (string)obj2;
                }
                return string.Empty;
            }
            set
            {
                this.ViewState["PagedControlID"] = value;
                this.dataPager.PagedControlID = value; //DataPage Setting
            }
        }

        [Browsable(true), GlobalizeCategory("Paging"), DefaultValue(false), GlobalizeDescription("UrlPaging")]
        public bool UrlPaging
        {
            get
            {
                object obj = ViewState["UrlPaging"];
                return (null == obj) ? false : (bool)obj;
            }
            set
            {
                ViewState["UrlPaging"] = value;
            }
        }

        [Browsable(true), DefaultValue("page"), GlobalizeCategory("Paging"), GlobalizeDescription("UrlPageIndexName")]
        public string UrlPageIndexName
        {
            get
            {
                object obj = ViewState["UrlPageIndexName"];
                return (null == obj) ? "page" : (string)obj;
            }
            set { ViewState["UrlPageIndexName"] = value; }
        }

        [Browsable(true), DefaultValue(""), GlobalizeCategory("Paging"), GlobalizeDescription("UrlPageSizeName")]
        public string UrlPageSizeName
        {
            get
            {
                return (string)ViewState["UrlPageSizeName"];
            }
            set { ViewState["UrlPageSizeName"] = value; }
        }

        [Browsable(true), DefaultValue(false), GlobalizeCategory("Paging"), GlobalizeDescription("ReverseUrlPageIndex")]
        public bool ReverseUrlPageIndex
        {
            get
            {
                object obj = ViewState["ReverseUrlPageIndex"];
                return (null == obj) ? false : (bool)obj;
            }
            set { ViewState["ReverseUrlPageIndex"] = value; }
        }

        [Browsable(true), GlobalizeDescription("CurrentPageIndex"), GlobalizeCategory("Paging"), DefaultValue(1)]
        public int CurrentPageIndex
        {
            get
            {
                object cpage = ViewState["CurrentPageIndex"];
                int pindex = (cpage == null) ? 1 : (int)cpage;
                if (pindex > PageCount && PageCount > 0)
                    return PageCount;
                if (pindex < 1)
                    return 1;
                return pindex;
            }
            set
            {
                int cpage = value;
                if (cpage < 1)
                    cpage = 1;
                ViewState["CurrentPageIndex"] = cpage;
                if (!pageChangeEventHandled)
                {
                    OnPageChanging(new PageChangingEventArgs(cpage));
                }
            }
        }


        [Browsable(false), GlobalizeDescription("RecordCount"), Category("Data"), DefaultValue(0)]
        public int RecordCount
        {
            get
            {
                object obj = ViewState["Recordcount"];
                return (obj == null) ? 0 : (int)obj;
            }
            set { ViewState["Recordcount"] = value;  }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int PagesRemain
        {
            get
            {
                return PageCount - CurrentPageIndex;
            }
        }


        [Browsable(true), GlobalizeDescription("PageSize"), GlobalizeCategory("Paging"), DefaultValue(10)]
        public int PageSize
        {
            get
            {
                if (!string.IsNullOrEmpty(UrlPageSizeName) && !DesignMode)
                {
                    int pageSize;
                    if (int.TryParse(Page.Request.QueryString[UrlPageSizeName], out pageSize))
                    {
                        if (pageSize > 0)
                            return pageSize;
                    }
                }
                ;
                object obj = ViewState["PageSize"];
                return (obj == null) ? 10 : (int)obj;
            }
            set
            {
                ViewState["PageSize"] = value;
                this.dataPager.PageSize = value;//DataPager setting
            }
        }


        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int RecordsRemain
        {
            get
            {
                if (CurrentPageIndex < PageCount)
                    return RecordCount - (CurrentPageIndex * PageSize);
                return 0;
            }
        }


        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int StartRecordIndex
        {
            get
            {
                return (CurrentPageIndex - 1) * PageSize /*+ 1*/;
            }
        }


        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int EndRecordIndex
        {
            get
            {
                return RecordCount - RecordsRemain;
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int PageCount
        {
            get
            {
                if (RecordCount == 0)
                    return 1;
                return (int)Math.Ceiling((double)RecordCount / (double)PageSize);
            }
        }


        #endregion

        #region Page index box


        [Browsable(true), GlobalizeCategory("PageIndexBox"), DefaultValue(ShowPageIndexBox.Auto), GlobalizeDescription("ShowPageIndexBox")]
        public ShowPageIndexBox ShowPageIndexBox
        {
            get
            {
                object obj = ViewState["ShowPageIndexBox"];
                return (obj == null) ? ShowPageIndexBox.Auto : (ShowPageIndexBox)obj;
            }
            set { ViewState["ShowPageIndexBox"] = value; }
        }


        [Browsable(true), GlobalizeCategory("PageIndexBox"), DefaultValue(PageIndexBoxType.TextBox), GlobalizeDescription("PageIndexBoxType")]
        public PageIndexBoxType PageIndexBoxType
        {
            get
            {
                object obj = ViewState["PageIndexBoxType"];
                return (obj == null) ? PageIndexBoxType.TextBox : (PageIndexBoxType)obj;
            }
            set
            {
                ViewState["PageIndexBoxType"] = value;
            }
        }



        [Browsable(true), GlobalizeCategory("PageIndexBox"), DefaultValue("pager_input"), GlobalizeDescription("PageIndexBoxClasss")]
        public string PageIndexBoxClass
        {
            get
            {
                object obj = ViewState["PageIndexBoxClass"];
                return (obj == null) ? "pager_input" : (string)obj;
            }
            set
            {
                if (value.Trim().Length > 0)
                    ViewState["PageIndexBoxClass"] = value;
            }
        }



        [Browsable(true), GlobalizeCategory("PageIndexBox"), DefaultValue(null), GlobalizeDescription("PageIndexBoxStyle")]
        public string PageIndexBoxStyle
        {
            get
            {
                object obj = ViewState["PageIndexBoxStyle"];
                return (obj == null) ? "height:15px" : (string)obj;
            }
            set
            {
                if (value.Trim().Length > 0)
                    ViewState["PageIndexBoxStyle"] = value;
            }
        }



        [Browsable(true), Themeable(true), GlobalizeCategory("PageIndexBox"), DefaultValue(null), GlobalizeDescription("TextBeforePageIndexBox")]
        public string TextBeforePageIndexBox
        {
            get
            {
                object obj = ViewState["TextBeforePageIndexBox"];
                return (null == obj) ? null : (string)obj;
            }
            set
            {
                ViewState["TextBeforePageIndexBox"] = value;
            }
        }



        [Browsable(true), Themeable(true), DefaultValue(null), GlobalizeCategory("PageIndexBox"), GlobalizeDescription("TextAfterPageIndexBox")]
        public string TextAfterPageIndexBox
        {
            get
            {

                object obj = ViewState["TextAfterPageIndexBox"];
                return (null == obj) ? null : (string)obj;
            }
            set
            {
                ViewState["TextAfterPageIndexBox"] = value;
            }
        }


        [Browsable(true), Themeable(true), GlobalizeCategory("PageIndexBox"), DefaultValue("go"), GlobalizeDescription("SubmitButtonText")]
        public string SubmitButtonText
        {
            get
            {
                object obj = ViewState["SubmitButtonText"];
                return (null == obj) ? "go" : (string)obj;
            }
            set
            {
                if (null == value)
                    value = "go";
                ViewState["SubmitButtonText"] = value;
            }
        }


        [Browsable(true), GlobalizeCategory("PageIndexBox"), DefaultValue("pager_button"), GlobalizeDescription("SubmitButtonClass")]
        public string SubmitButtonClass
        {
            get
            {
                object obj = ViewState["SubmitButtonClass"];
                return (null == obj) ? "pager_button" : (string)obj;
            }
            set
            {
                ViewState["SubmitButtonClass"] = value;
            }
        }


        [Browsable(true), GlobalizeCategory("PageIndexBox"), DefaultValue(null), GlobalizeDescription("SubmitButtonStyle")]
        public string SubmitButtonStyle
        {
            get
            {

                return (string)ViewState["SubmitButtonStyle"];
            }
            set
            {
                ViewState["SubmitButtonStyle"] = value;
            }
        }


        [Browsable(false), DefaultValue(""), Category("Appearance"), GlobalizeDescription("SubmitButtonImageUrl")]
        public string SubmitButtonImageUrl
        {
            get
            {
                if(string.IsNullOrEmpty(this.submitButtonImageUrl))
                    this.submitButtonImageUrl=this.ImagePath+"go.gif";
                return this.submitButtonImageUrl;
            }
            set {this.submitButtonImageUrl= value; }
        }


        [Browsable(true), Themeable(true), GlobalizeDescription("ShowBoxThreshold"), GlobalizeCategory("PageIndexBox"), DefaultValue(30)]
        public int ShowBoxThreshold
        {
            get
            {
                object obj = ViewState["ShowBoxThreshold"];
                return (null == obj) ? 30 : (int)obj;
            }
            set { ViewState["ShowBoxThreshold"] = value; }
        }


        #endregion

        #region CustomInfoSection


        [Browsable(true), Themeable(true), GlobalizeDescription("ShowCustomInfoSection"), DefaultValue(ShowCustomInfoSection.Never), Category("Appearance")]
        public ShowCustomInfoSection ShowCustomInfoSection
        {
            get
            {
                object obj = ViewState["ShowCustomInfoSection"];
                return (null == obj) ? ShowCustomInfoSection.Never : (ShowCustomInfoSection)obj;
            }
            set { ViewState["ShowCustomInfoSection"] = value; }
        }


        [Browsable(true), Category("Appearance"), DefaultValue(HorizontalAlign.NotSet), GlobalizeDescription("CustomInfoTextAlign")]
        public HorizontalAlign CustomInfoTextAlign
        {
            get
            {
                object obj = ViewState["CustomInfoTextAlign"];
                return (null == obj) ? HorizontalAlign.NotSet : (HorizontalAlign)obj;
            }
            set
            {
                ViewState["CustomInfoTextAlign"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), DefaultValue(typeof(Unit), "40%"), GlobalizeDescription("CustomInfoSectionWidth")]
        public Unit CustomInfoSectionWidth
        {
            get
            {
                object obj = ViewState["CustomInfoSectionWidth"];
                return (null == obj) ? Unit.Percentage(40) : (Unit)obj;
            }
            set
            {
                ViewState["CustomInfoSectionWidth"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), DefaultValue(null), GlobalizeDescription("CustomInfoClass")]
        public string CustomInfoClass
        {
            get
            {
                object obj = ViewState["CustomInfoClass"];
                return (null == obj) ? CssClass : (string)obj;
            }
            set
            {
                ViewState["CustomInfoClass"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), DefaultValue(null), GlobalizeDescription("CustomInfoStyle")]
        public string CustomInfoStyle
        {
            get
            {
                object obj = ViewState["CustomInfoStyle"];
                return (null == obj) ? Style.Value : (string)obj;
            }
            set
            {
                ViewState["CustomInfoStyle"] = value;
            }
        }

        [Browsable(true), Themeable(true), Category("Appearance"), DefaultValue("Orders:%RecordCount%  Page:%CurrentPageIndex% of %PageCount%"), GlobalizeDescription("CustomInfoHTML")]
        public string CustomInfoHTML
        {
            get
            {
                object obj = ViewState["CustomInfoText"];
                return (null == obj) ? "Orders:%RecordCount%  Page:%CurrentPageIndex% of %PageCount%" : (string)obj;
            }
            set
            {
                ViewState["CustomInfoText"] = value;
            }
        }

        #endregion

        #region Css class and styles


        [Browsable(true), Category("Appearance"), Themeable(true), GlobalizeDescription("CurrentPageButtonStyle"), DefaultValue(null)]
        public string CurrentPageButtonStyle
        {
            get
            {
                object obj = ViewState["CPBStyle"];
                return (null == obj) ? null : (string)obj;
            }
            set
            {
                ViewState["CPBStyle"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), Themeable(true), GlobalizeDescription("CurrentPageButtonClass"), DefaultValue(null)]
        public string CurrentPageButtonClass
        {
            get
            {
                object obj = ViewState["CPBClass"];
                return (null == obj) ? null : (string)obj;
            }
            set
            {
                ViewState["CPBClass"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), Themeable(true), GlobalizeDescription("PagingButtonClass"), DefaultValue(null)]
        public string PagingButtonClass
        {
            get
            {

                object obj = ViewState["PagingButtonClass"];
                return (null == obj) ? null : (string)obj;
            }
            set
            {
                ViewState["PagingButtonClass"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), Themeable(true), GlobalizeDescription("PagingButtonStyle"), DefaultValue(null)]
        public string PagingButtonStyle
        {
            get
            {

                object obj = ViewState["PagingButtonStyle"];
                return (null == obj) ? null : (string)obj;
            }
            set
            {
                ViewState["PagingButtonStyle"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), Themeable(true), GlobalizeDescription("FirstLastButtonClass"), DefaultValue(null)]
        public string FirstLastButtonClass
        {
            get
            {
                object obj = ViewState["FirstLastButtonClass"];
                return (null == obj) ? PagingButtonClass : (string)obj;
            }
            set
            {
                ViewState["FirstLastButtonClass"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), Themeable(true), GlobalizeDescription("FirstLastButtonStyle"), DefaultValue(null)]
        public string FirstLastButtonStyle
        {
            get
            {
                object obj = ViewState["FirstLastButtonStyle"];
                return (null == obj) ? PagingButtonStyle : (string)obj;
            }
            set
            {
                ViewState["FirstLastButtonStyle"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), Themeable(true), GlobalizeDescription("NextPrevButtonClass"), DefaultValue(null)]
        public string NextPrevButtonClass
        {
            get
            {
                object obj = ViewState["NextPrevButtonClass"];
                return (null == obj) ? PagingButtonClass : (string)obj;
            }
            set
            {
                ViewState["NextPrevButtonClass"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), Themeable(true), GlobalizeDescription("NextPrevButtonStyle"), DefaultValue(null)]
        public string NextPrevButtonStyle
        {
            get
            {
                object obj = ViewState["NextPrevButtonStyle"];
                return (null == obj) ? PagingButtonStyle : (string)obj;
            }
            set
            {
                ViewState["NextPrevButtonStyle"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), Themeable(true), GlobalizeDescription("MoreButtonClass"), DefaultValue(null)]
        public string MoreButtonClass
        {
            get
            {
                object obj = ViewState["MoreButtonClass"];
                return (null == obj) ? PagingButtonClass : (string)obj;
            }
            set
            {
                ViewState["MoreButtonClass"] = value;
            }
        }


        [Browsable(true), Category("Appearance"), Themeable(true), GlobalizeDescription("MoreButtonStyle"), DefaultValue(null)]
        public string MoreButtonStyle
        {
            get
            {
                object obj = ViewState["MoreButtonStyle"];
                return (null == obj) ? PagingButtonStyle : (string)obj;
            }
            set
            {
                ViewState["MoreButtonStyle"] = value;
            }
        }

        #endregion

        #region Others


        [Browsable(true), Themeable(true), Category("Behavior"), DefaultValue(false), GlobalizeDescription("AlwaysShow")]
        public bool AlwaysShow
        {
            get
            {
                object obj = ViewState["AlwaysShow"];
                if (null == obj)
                {
                    return false;
                }
                return (bool)obj;
            }
            set
            {
                ViewState["AlwaysShow"] = value;
            }
        }

        public override string ID
        {
            get
            {
                return base.ID;
            }
            set
            {
                base.ID = value;
                this.dataPager.ID = value + "_DataPage";
                
            }
        }

        public override bool Wrap
        {
            get
            {
                return base.Wrap;
            }
            set
            {
                base.Wrap = false;
            }
        }

        //[Browsable(true), Themeable(true), GlobalizeDescription("PIOutOfRangeMsg"), ANPDefaultValue("def_PIOutOfRangerMsg"), Category("Data")]
        //public string PageIndexOutOfRangeErrorMessage
        //{
        //    get
        //    {
        //        object obj = ViewState["PIOutOfRangeErrorMsg"];
        //        if (null == obj)
        //        {
        //            if (null != cloneFrom)
        //                return cloneFrom.PageIndexOutOfRangeErrorMessage;
        //            return SR.GetString("def_PIOutOfRangerMsg");
        //        }
        //        return (string)obj;
        //    }
        //    set
        //    {
        //        ViewState["PIOutOfRangeErrorMsg"] = value;
        //    }
        //}

        //[Browsable(true), Themeable(true), GlobalizeDescription("InvalidPIErrorMsg"), ANPDefaultValue("def_InvalidPIErrorMsg"), Category("Data")]
        //public string InvalidPageIndexErrorMessage
        //{
        //    get
        //    {
        //        object obj = ViewState["InvalidPIErrorMsg"];
        //        if (null == obj)
        //        {
        //            if (null != cloneFrom)
        //                return cloneFrom.InvalidPageIndexErrorMessage;
        //            return SR.GetString("def_InvalidPIErrorMsg");
        //        }
        //        return (string)obj;
        //    }
        //    set
        //    {
        //        ViewState["InvalidPIErrorMsg"] = value;
        //    }
        //}


        [Browsable(true), DefaultValue(LayoutType.Div), Themeable(true), GlobalizeDescription("LayoutType"), Category("Appearance")]
        public LayoutType LayoutType
        {
            get
            {
                object obj = ViewState["LayoutType"];
                return (null == obj) ? LayoutType.Div : (LayoutType)obj;
            }
            set { ViewState["LayoutType"] = value; }
        }

        #endregion

        #endregion

        #region construct method

        public Pager()
        {
            this.dataPager = new DataPager();
        }
        #endregion


        #region IPostBackEventHandler Implementation


        public void RaisePostBackEvent(string args)
        {
            int pageIndex = CurrentPageIndex;
            try
            {
                if (string.IsNullOrEmpty(args))
                    args = inputPageIndex;
                pageIndex = int.Parse(args);
            }
            catch { }
            PageChangingEventArgs pcArgs = new PageChangingEventArgs(pageIndex);

            OnPageChanging(pcArgs);
        }

        #endregion

        #region IPostBackDataHandler Implementation

        public virtual bool LoadPostData(string pkey, NameValueCollection pcol)
        {
            string str = pcol[UniqueID + "_input"];
            if (str != null && str.Trim().Length > 0)
            {
                try
                {
                    int pindex = int.Parse(str);
                    if (pindex > 0 && pindex <= PageCount)
                    {
                        inputPageIndex = str;
                        Page.RegisterRequiresRaiseEvent(this);
                    }
                }
                catch { }
            }
            return false;
        }


        public virtual void RaisePostDataChangedEvent() { }

        #endregion

        #region Events

        public event PageChangingEventHandler PageChanging
        {
            add
            {
                Events.AddHandler(EventPageChanging, value);
            }
            remove
            {
                Events.RemoveHandler(EventPageChanging, value);
            }
        }

        public event EventHandler PageChanged
        {
            add
            {
                Events.AddHandler(EventPageChanged, value);
            }
            remove
            {
                Events.RemoveHandler(EventPageChanged, value);
            }
        }

        #endregion

        #region Methods

        protected virtual void OnPageChanging(PageChangingEventArgs e)
        {
            pageChangeEventHandled = true;
            PageChangingEventHandler handler = (PageChangingEventHandler)Events[EventPageChanging];
            if (handler != null)
            {
                handler(this, e);
                if (!e.Cancel || UrlPaging)
                {
                    CurrentPageIndex = e.NewPageIndex;
                    this.dataPager.SetPageProperties(this.StartRecordIndex, this.PageSize, true);//DataPager setting
                    OnPageChanged(EventArgs.Empty);
                }
            }
            else
            {
                CurrentPageIndex = e.NewPageIndex;
                this.dataPager.SetPageProperties(this.StartRecordIndex, this.PageSize, true);////DataPager setting
                OnPageChanged(EventArgs.Empty);
            }
            pageChangeEventHandled = false;
        }

        protected virtual void OnPageChanged(EventArgs e)
        {
            EventHandler handler = (EventHandler)Events[EventPageChanged];
            if (handler != null)
                handler(this, e);
        }

        #endregion

        #region Private Helper Functions


        private void RenderCustomInfoSection(HtmlTextWriter writer)
        {
            if (Height != Unit.Empty)
                writer.AddStyleAttribute(HtmlTextWriterStyle.Height, Height.ToString());
            string customUnit = CustomInfoSectionWidth.ToString();
            if (CustomInfoClass != null && CustomInfoClass.Trim().Length > 0)
                writer.AddAttribute(HtmlTextWriterAttribute.Class, CustomInfoClass);
            if (CustomInfoStyle != null && CustomInfoStyle.Trim().Length > 0)
                writer.AddAttribute(HtmlTextWriterAttribute.Style, CustomInfoStyle);
            writer.AddStyleAttribute(HtmlTextWriterStyle.Width, customUnit);
            if (CustomInfoTextAlign != HorizontalAlign.NotSet)
                writer.AddAttribute(HtmlTextWriterAttribute.Align, CustomInfoTextAlign.ToString().ToLower());
            if (LayoutType == LayoutType.Div)
            {
                writer.AddStyleAttribute("float", "left");
                writer.AddAttribute(HtmlTextWriterAttribute.Valign, "middle");
                writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
                writer.RenderBeginTag(HtmlTextWriterTag.Div);
            }
            else
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Valign, "middle");
                writer.AddAttribute(HtmlTextWriterAttribute.Nowrap, "true");
                writer.RenderBeginTag(HtmlTextWriterTag.Td);
            }
            writer.Write(GetCustomInfoHTML(CustomInfoHTML));
            writer.RenderEndTag();
        }

        private void RenderNavigationSection(HtmlTextWriter writer)
        {
            if (CustomInfoSectionWidth.Type == UnitType.Percentage)
            {
                writer.AddStyleAttribute(HtmlTextWriterStyle.Width,
                                         (Unit.Percentage(100 - CustomInfoSectionWidth.Value)).ToString());
            }
            if (HorizontalAlign != HorizontalAlign.NotSet)
                writer.AddAttribute(HtmlTextWriterAttribute.Align, HorizontalAlign.ToString().ToLower());
            if (!string.IsNullOrEmpty(CssClass))
                writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
            if (LayoutType == LayoutType.Div)
            {
                writer.AddStyleAttribute("float", "left");
                if (NavigationSectionAlign != HorizontalAlign.NotSet)
                   writer.AddAttribute(HtmlTextWriterAttribute.Align, NavigationSectionAlign.ToString().ToLower());
                writer.RenderBeginTag(HtmlTextWriterTag.Div); //<div>
            }
            else
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Valign, "middle");
                writer.AddAttribute(HtmlTextWriterAttribute.Nowrap, "true");
                if (NavigationSectionAlign != HorizontalAlign.NotSet)
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, NavigationSectionAlign.ToString().ToLower());
                writer.RenderBeginTag(HtmlTextWriterTag.Td); //<td>
            }
            RenderPagingElements(writer);
            writer.RenderEndTag(); //</div> or </td>
        }

        private void RenderPagingElements(HtmlTextWriter writer)
        {
            int startIndex = ((CurrentPageIndex - 1) / NumericButtonCount) * NumericButtonCount; //this is an important trick, it's not the same as CurrentPageIndex-1
            if (PageCount > NumericButtonCount && CurrentPageButtonPosition != PagingButtonPosition.Fixed)
            {
                switch (CurrentPageButtonPosition)
                {
                    case PagingButtonPosition.End:
                        if (CurrentPageIndex > NumericButtonCount)
                            startIndex = CurrentPageIndex - NumericButtonCount;
                        break;
                    case PagingButtonPosition.Center:
                        int startOffset = CurrentPageIndex - (int)(Math.Ceiling((double)NumericButtonCount / 2));
                        if (startOffset > 0)
                        {
                            startIndex = startOffset;
                            if (startIndex > (PageCount - NumericButtonCount))
                                startIndex = PageCount - NumericButtonCount;
                        }
                        break;
                    case PagingButtonPosition.Beginning:
                        startIndex = CurrentPageIndex - 1;
                        if (startIndex + NumericButtonCount > PageCount)
                            startIndex = PageCount - NumericButtonCount;
                        break;
                }
            }

            int endIndex = ((startIndex + NumericButtonCount) > PageCount) ? PageCount : (startIndex + NumericButtonCount);

            if (PagingButtonLayoutType == PagingButtonLayoutType.UnorderedList)
                writer.RenderBeginTag(HtmlTextWriterTag.Ul); //<ul>

            CreateNavigationButton(writer, PagerItemType.First);
            CreateNavigationButton(writer, PagerItemType.Prev);
            if (ShowPageIndex)
            {
                if (startIndex > 0)
                    CreateMoreButton(writer, startIndex);
                for (int i = startIndex + 1; i <= endIndex; i++)
                {
                    CreateNumericButton(writer, i);
                }
                if (PageCount > NumericButtonCount && endIndex < PageCount)
                    CreateMoreButton(writer, endIndex + 1);
            }
            CreateNavigationButton(writer, PagerItemType.Next);
            CreateNavigationButton(writer, PagerItemType.Last);

            if (PagingButtonLayoutType == PagingButtonLayoutType.UnorderedList)
                writer.RenderEndTag(); //</ul>


            if ((ShowPageIndexBox == ShowPageIndexBox.Always) || (ShowPageIndexBox == ShowPageIndexBox.Auto && PageCount >= ShowBoxThreshold))
            {
                string boxClientId = UniqueID + "_input";
                writer.Write("&nbsp;&nbsp;");
                if (!string.IsNullOrEmpty(TextBeforePageIndexBox))
                    writer.Write(TextBeforePageIndexBox);
                if (PageIndexBoxType == PageIndexBoxType.TextBox) //TextBox
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
                    writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "30px");
                    writer.AddAttribute(HtmlTextWriterAttribute.Value, CurrentPageIndex.ToString());
                    if (!string.IsNullOrEmpty(PageIndexBoxStyle))
                        writer.AddAttribute(HtmlTextWriterAttribute.Style, PageIndexBoxStyle);
                    if (!string.IsNullOrEmpty(PageIndexBoxClass))
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, PageIndexBoxClass);
                    if (!Enabled || (PageCount <= 1 && AlwaysShow))
                        writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
                    writer.AddAttribute(HtmlTextWriterAttribute.Name, boxClientId);
                    writer.AddAttribute(HtmlTextWriterAttribute.Id, boxClientId);
                    string chkInputScript = "ANP_checkInput(\'" + boxClientId + "\'," + PageCount + ")";
                    string keydownScript = "ANP_keydown(event,\'" + UniqueID + "_btn\');";
                    string clickScript = "if(" + chkInputScript + "){ANP_goToPage(document.getElementById(\'" + boxClientId + "\'));};return false;";

                    writer.AddAttribute("onkeydown", keydownScript);
                    writer.RenderBeginTag(HtmlTextWriterTag.Input);
                    writer.RenderEndTag();
                    //Text after page index box
                    if (!string.IsNullOrEmpty(TextAfterPageIndexBox))
                        writer.Write(TextAfterPageIndexBox);

                    //button
                    if (!string.IsNullOrEmpty(SubmitButtonImageUrl))
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Type, "image");
                        writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
                        writer.AddAttribute(HtmlTextWriterAttribute.Src, SubmitButtonImageUrl);
                    }
                    else
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Type, UrlPaging ? "button" : "submit");
                        writer.AddAttribute(HtmlTextWriterAttribute.Value, SubmitButtonText);
                    }
                    writer.AddAttribute(HtmlTextWriterAttribute.Name, UniqueID);
                    writer.AddAttribute(HtmlTextWriterAttribute.Id, UniqueID + "_btn");
                    if (!string.IsNullOrEmpty(SubmitButtonClass))
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, SubmitButtonClass);
                    if (!string.IsNullOrEmpty(SubmitButtonStyle))
                        writer.AddAttribute(HtmlTextWriterAttribute.Style, SubmitButtonStyle);
                    if (!Enabled || (PageCount <= 1 && AlwaysShow))
                        writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
                    writer.AddAttribute(HtmlTextWriterAttribute.Onclick, (UrlPaging) ? clickScript : "if(" + chkInputScript + "){" + Page.ClientScript.GetPostBackEventReference(this, null) + "} else{return false}");
                    writer.RenderBeginTag(HtmlTextWriterTag.Input);
                    writer.RenderEndTag();
                }
                else //Dropdownlist
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Name, boxClientId);
                    writer.AddAttribute(HtmlTextWriterAttribute.Id, boxClientId);
                    writer.AddAttribute(HtmlTextWriterAttribute.Onchange, UrlPaging ? "ANP_goToPage(this)" : Page.ClientScript.GetPostBackEventReference(this, null));
                    writer.RenderBeginTag(HtmlTextWriterTag.Select);
                    if (PageCount > 80) //list only part of page indices
                    {
                        if (CurrentPageIndex <= 15)
                        {
                            listPageIndices(writer, 1, 15);
                            addMoreListItem(writer, 16);
                            listPageIndices(writer, PageCount - 4, PageCount);
                        }
                        else if (CurrentPageIndex >= PageCount - 14)
                        {
                            listPageIndices(writer, 1, 5);
                            addMoreListItem(writer, PageCount - 15);
                            listPageIndices(writer, PageCount - 14, PageCount);
                        }
                        else
                        {
                            listPageIndices(writer, 1, 5);
                            addMoreListItem(writer, CurrentPageIndex - 6);
                            listPageIndices(writer, CurrentPageIndex - 5, CurrentPageIndex + 5);
                            addMoreListItem(writer, CurrentPageIndex + 6);
                            listPageIndices(writer, PageCount - 4, PageCount);
                        }
                    }
                    else //list all page indices
                        listPageIndices(writer, 1, PageCount);
                    writer.RenderEndTag();
                    if (!string.IsNullOrEmpty(TextAfterPageIndexBox))
                        writer.Write(TextAfterPageIndexBox);
                }
            }
        }

        /// <summary>
        /// Get the navigation url for the paging button.
        /// </summary>
        /// <param name="pageIndex">the page index correspond to the button.</param>
        /// <returns>href string for the paging navigation button.</returns>
        private string GetHrefString(int pageIndex)
        {
            if (UrlPaging)
            {
                int urlPageIndex = pageIndex;
                string jsValue = "pi";
                if (ReverseUrlPageIndex)
                {
                    jsValue = "(" + PageCount + "-pi+1)";
                    urlPageIndex = pageIndex == -1 ? -1 : PageCount - pageIndex + 1;
                }
                //if (EnableUrlRewriting)
                //{
                //    Regex reg = new Regex("(?<p>%(?<m>[^%]+)%)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                //    MatchCollection mts = reg.Matches(UrlRewritePattern);
                //    string prmValue;
                //    NameValueCollection urlParams = ConvertQueryStringToCollection(queryString);
                //    string url = UrlRewritePattern;
                //    foreach (Match m in mts)
                //    {
                //        prmValue = urlParams[m.Groups["m"].Value];
                //        //if (prmValue != null)
                //        url = url.Replace(m.Groups["p"].Value, prmValue);
                //    }
                //    return
                //        ResolveUrl(string.Format(url,
                //                                 (urlPageIndex == -1) ? "\"+" + jsValue + "+\"" : urlPageIndex.ToString()));
                //}
                return BuildUrlString(UrlPageIndexName,
                                      (urlPageIndex == -1) ? "\"+" + jsValue + "+\"" : urlPageIndex.ToString());
            }
            return Page.ClientScript.GetPostBackClientHyperlink(this, pageIndex.ToString());
        }

        /// <summary>
        /// Replace the property placeholders in the CustomInfoHTML with the property values repectively
        /// </summary>
        /// <param name="origText">original CustomInfoHTML</param>
        /// <returns></returns>
        private string GetCustomInfoHTML(string origText)
        {
            if (!string.IsNullOrEmpty(origText) && origText.IndexOf('%') >= 0)
            {
                string[] props = new string[] { "recordcount", "pagecount", "currentpageindex", "startrecordindex", "endrecordindex", "pagesize", "pagesremain", "recordsremain" };
                StringBuilder sb = new StringBuilder(origText);
                Regex reg = new Regex("(?<ph>%(?<pname>\\w{8,})%)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                MatchCollection mts = reg.Matches(origText);
                foreach (Match m in mts)
                {
                    string p = m.Groups["pname"].Value.ToLower();
                    if (Array.IndexOf(props, p) >= 0)
                    {
                        string repValue = null;
                        switch (p)
                        {
                            case "recordcount":
                                repValue = RecordCount.ToString(); break;
                            case "pagecount":
                                repValue = PageCount.ToString(); break;
                            case "currentpageindex":
                                repValue = CurrentPageIndex.ToString(); break;
                            case "startrecordindex":
                                repValue = StartRecordIndex.ToString(); break;
                            case "endrecordindex":
                                repValue = EndRecordIndex.ToString(); break;
                            case "pagesize":
                                repValue = PageSize.ToString(); break;
                            case "pagesremain":
                                repValue = PagesRemain.ToString(); break;
                            case "recordsremain":
                                repValue = RecordsRemain.ToString(); break;
                        }
                        if (repValue != null)
                            sb.Replace(m.Groups["ph"].Value, repValue);
                    }
                }
                return sb.ToString();
            }
            return origText;
        }

        /// <summary>
        /// Convert raw query string to NameValueCollection
        /// </summary>
        /// <param name="s">raw query string</param>
        private static NameValueCollection ConvertQueryStringToCollection(string s)
        {
            NameValueCollection prms = new NameValueCollection();
            int num = (s != null) ? s.Length : 0;
            for (int i = 0; i < num; i++)
            {
                int startIndex = i;
                int num4 = -1;
                while (i < num)
                {
                    char ch = s[i];
                    if (ch == '=')
                    {
                        if (num4 < 0)
                        {
                            num4 = i;
                        }
                    }
                    else if (ch == '&')
                    {
                        break;
                    }
                    i++;
                }
                string skey = null;
                string svalue;
                if (num4 >= 0)
                {
                    skey = s.Substring(startIndex, num4 - startIndex);
                    svalue = s.Substring(num4 + 1, (i - num4) - 1);
                }
                else
                {
                    svalue = s.Substring(startIndex, i - startIndex);
                }
                prms.Add(skey, svalue);
                if ((i == (num - 1)) && (s[i] == '&'))
                {
                    prms.Add(null, string.Empty);
                }
            }
            return prms;
        }

        /// <summary>
        /// add paging parameter and value to the current url or change parameter value if it already exists when using url paging mode
        /// </summary>
        /// <param name="sk">name of the url parameter to be added</param>
        /// <param name="sv">value of the url paramter to be added</param>
        /// <returns>href string for the navigattion buttn</returns>
        private string BuildUrlString(string sk, string sv)
        {
            StringBuilder ubuilder = new StringBuilder(80);
            bool keyFound = false;
            int num = (queryString != null) ? queryString.Length : 0;
            for (int i = 0; i < num; i++)
            {
                int startIndex = i;
                int num4 = -1;
                while (i < num)
                {
                    char ch = queryString[i];
                    if (ch == '=')
                    {
                        if (num4 < 0)
                        {
                            num4 = i;
                        }
                    }
                    else if (ch == '&')
                    {
                        break;
                    }
                    i++;
                }
                string skey = null;
                string svalue;
                if (num4 >= 0)
                {
                    skey = queryString.Substring(startIndex, num4 - startIndex);
                    svalue = queryString.Substring(num4 + 1, (i - num4) - 1);
                }
                else
                {
                    svalue = queryString.Substring(startIndex, i - startIndex);
                }
                ubuilder.Append(skey).Append("=");
                if (skey == sk)
                {
                    keyFound = true;
                    ubuilder.Append(sv);
                }
                else
                    ubuilder.Append(svalue);
                ubuilder.Append("&");
            }
            if (!keyFound)
                ubuilder.Append(sk).Append("=").Append(sv);
            ubuilder.Insert(0, "?").Insert(0, System.IO.Path.GetFileName(currentUrl));
            return ubuilder.ToString().Trim('&');
        }

        /// <summary>
        /// Create first, prev, next or last button.
        /// </summary>
        /// <param name="writer">A <see cref="System.Web.UI.HtmlTextWriter"/> that represents the output stream to render HTML content on the client.</param>
        /// <param name="itemType">pager item type</param>
        private void CreateNavigationButton(HtmlTextWriter writer, PagerItemType itemType)
        {
            if (!ShowFirstLast && (itemType == PagerItemType.First || itemType == PagerItemType.Last))
                return;
            if (!ShowPrevNext && (itemType == PagerItemType.Prev || itemType == PagerItemType.Next))
                return;
            if (itemType == PagerItemType.First || itemType == PagerItemType.Last) //first page or last page button
                AddClassAndStyle(FirstLastButtonClass, FirstLastButtonStyle, writer);
            else
                AddClassAndStyle(NextPrevButtonClass, NextPrevButtonStyle, writer);//next page or prevous page button
            AddPagingButtonLayoutTag(writer); //<li> or <span>

            string linktext;
            bool disabled;
            int pageIndex;
            bool imgButton = (PagingButtonType == PagingButtonType.Image &&
                              NavigationButtonType == PagingButtonType.Image);
            if (itemType == PagerItemType.Prev || itemType == PagerItemType.First)
            {
                disabled = (CurrentPageIndex <= 1) | !Enabled;
                if (!ShowDisabledButtons && disabled)
                    return;
                pageIndex = (itemType == PagerItemType.First) ? 1 : (CurrentPageIndex - 1);
                writeSpacingStyle(writer);
                if (PagingButtonLayoutType == PagingButtonLayoutType.None) //add css class and style attribute to pager item directly
                {
                    if (itemType == PagerItemType.First || itemType == PagerItemType.Last) //first page or last page button
                        AddClassAndStyle(FirstLastButtonClass, FirstLastButtonStyle, writer);
                    else
                        AddClassAndStyle(NextPrevButtonClass, NextPrevButtonStyle, writer);//next page or prevous page button
                }
                if (imgButton)
                {
                    if (!disabled)
                    {

                        writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(pageIndex));
                        AddToolTip(writer, pageIndex);
                        AddHyperlinkTarget(writer);
                        writer.RenderBeginTag(HtmlTextWriterTag.A);
                        writer.AddAttribute(HtmlTextWriterAttribute.Src,
                                            String.Concat(ImagePath, itemType.ToString(), ButtonImageNameExtension,
                                                          ButtonImageExtension));
                        writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
                        if (ButtonImageAlign != ImageAlign.NotSet)
                            writer.AddAttribute(HtmlTextWriterAttribute.Align, ButtonImageAlign.ToString());
                        writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
                        writer.RenderBeginTag(HtmlTextWriterTag.Img);
                        writer.RenderEndTag();
                        writer.RenderEndTag();
                    }
                    else
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Src,
                                            String.Concat(ImagePath, itemType.ToString(), DisabledButtonImageNameExtension,
                                                          ButtonImageExtension));
                        writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
                        if (ButtonImageAlign != ImageAlign.NotSet)
                            writer.AddAttribute(HtmlTextWriterAttribute.Align, ButtonImageAlign.ToString());
                        writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
                        writer.RenderBeginTag(HtmlTextWriterTag.Img);
                        writer.RenderEndTag();
                    }
                }
                else
                {
                    linktext = (itemType == PagerItemType.Prev) ? PrevPageText : FirstPageText;
                    if (disabled)
                        writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
                    else
                    {
                        AddToolTip(writer, pageIndex);
                        AddHyperlinkTarget(writer);
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(pageIndex));
                    }
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                    writer.Write(linktext);
                    writer.RenderEndTag();
                }
            }
            else
            {
                disabled = (CurrentPageIndex >= PageCount) | !Enabled;
                if (!ShowDisabledButtons && disabled)
                    return;
                pageIndex = (itemType == PagerItemType.Last) ? PageCount : (CurrentPageIndex + 1);
                writeSpacingStyle(writer);
                if (PagingButtonLayoutType == PagingButtonLayoutType.None) //add css class and style attribute to pager item directly
                {
                    if (itemType == PagerItemType.First || itemType == PagerItemType.Last) //first page or last page button
                        AddClassAndStyle(FirstLastButtonClass, FirstLastButtonStyle, writer);
                    else
                        AddClassAndStyle(NextPrevButtonClass, NextPrevButtonStyle, writer);//next page or prevous page button
                }
                if (imgButton)
                {
                    if (!disabled)
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(pageIndex));
                        AddToolTip(writer, pageIndex);
                        AddHyperlinkTarget(writer);
                        writer.RenderBeginTag(HtmlTextWriterTag.A);
                        writer.AddAttribute(HtmlTextWriterAttribute.Src,
                                            String.Concat(ImagePath, itemType.ToString(), ButtonImageNameExtension,
                                                          ButtonImageExtension));
                        writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
                        if (ButtonImageAlign != ImageAlign.NotSet)
                            writer.AddAttribute(HtmlTextWriterAttribute.Align, ButtonImageAlign.ToString());
                        writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
                        writer.RenderBeginTag(HtmlTextWriterTag.Img);
                        writer.RenderEndTag();
                        writer.RenderEndTag();
                    }
                    else
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Src,
                                            String.Concat(ImagePath, itemType.ToString(), DisabledButtonImageNameExtension,
                                                          ButtonImageExtension));
                        writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
                        if (ButtonImageAlign != ImageAlign.NotSet)
                            writer.AddAttribute(HtmlTextWriterAttribute.Align, ButtonImageAlign.ToString());
                        writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle");
                        writer.RenderBeginTag(HtmlTextWriterTag.Img);
                        writer.RenderEndTag();
                    }
                }
                else
                {
                    linktext = (itemType == PagerItemType.Next) ? NextPageText : LastPageText;
                    if (disabled)
                        writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
                    else
                    {
                        AddToolTip(writer, pageIndex);
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(pageIndex));
                        AddHyperlinkTarget(writer);
                    }
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                    writer.Write(linktext);
                    writer.RenderEndTag();
                }
            }
            if (PagingButtonLayoutType != PagingButtonLayoutType.None)
                writer.RenderEndTag(); //</li> or </span>
        }

        /// <summary>
        /// Add tool tip text to navigation button.
        /// </summary>
        private void AddToolTip(HtmlTextWriter writer, int pageIndex)
        {
            if (ShowNavigationToolTip)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Title, String.Format(NavigationToolTipTextFormatString, pageIndex));
            }
        }
        /// <summary>
        /// add paging button layout tag
        /// </summary>
        private void AddPagingButtonLayoutTag(HtmlTextWriter writer)
        {
            if (PagingButtonLayoutType == PagingButtonLayoutType.UnorderedList)
                writer.RenderBeginTag(HtmlTextWriterTag.Li); //<li>
            else if (PagingButtonLayoutType == PagingButtonLayoutType.Span)
                writer.RenderBeginTag(HtmlTextWriterTag.Span); //<span>
        }

        /// <summary>
        /// Create numeric paging button.
        /// </summary>
        /// <param name="writer">A <see cref="System.Web.UI.HtmlTextWriter"/> that represents the output stream to render HTML content on the client.</param>
        /// <param name="index">the page index correspond to the paging button</param>
        private void CreateNumericButton(HtmlTextWriter writer, int index)
        {
            bool isCurrent = (index == CurrentPageIndex);

            if ((!isCurrent && PagingButtonLayoutType != PagingButtonLayoutType.None) || (isCurrent && PagingButtonLayoutType == PagingButtonLayoutType.UnorderedList)) //current page button already wrapped in span
            {
                if (!isCurrent) //exclude current page index button
                    AddClassAndStyle(PagingButtonClass, PagingButtonStyle, writer);
                AddPagingButtonLayoutTag(writer); //<li>
            }

            if (PagingButtonType == PagingButtonType.Image && NumericButtonType == PagingButtonType.Image)
            {
                writeSpacingStyle(writer);
                if (!isCurrent)
                {
                    if (Enabled)
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(index));
                    if (PagingButtonLayoutType == PagingButtonLayoutType.None) //add css class and style attribute to hyper link directory
                        AddClassAndStyle(PagingButtonClass, PagingButtonStyle, writer);
                    AddToolTip(writer, index);
                    AddHyperlinkTarget(writer);
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                    CreateNumericImages(writer, index, false);
                    writer.RenderEndTag();
                }
                else
                {
                    AddClassAndStyle(CurrentPageButtonClass, CurrentPageButtonStyle, writer);
                    writer.RenderBeginTag(HtmlTextWriterTag.Span);
                    CreateNumericImages(writer, index, true);
                    writer.RenderEndTag();
                }
            }
            else
            {
                writeSpacingStyle(writer);
                if (isCurrent)
                {
                    if (string.IsNullOrEmpty(CurrentPageButtonClass) && string.IsNullOrEmpty(CurrentPageButtonStyle))
                    {
                        writer.AddStyleAttribute(HtmlTextWriterStyle.FontWeight, "Bold");
                        writer.AddStyleAttribute(HtmlTextWriterStyle.Color, "red");
                    }
                    else
                        AddClassAndStyle(CurrentPageButtonClass, CurrentPageButtonStyle, writer);
                    writer.RenderBeginTag(HtmlTextWriterTag.Span);
                    if (!string.IsNullOrEmpty(CurrentPageButtonTextFormatString))
                        writer.Write(String.Format(CurrentPageButtonTextFormatString, index));
                    else
                        writer.Write(index);
                    writer.RenderEndTag();
                }
                else
                {
                    if (Enabled)
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(index));
                    }
                    if (PagingButtonLayoutType == PagingButtonLayoutType.None) //add css class and style attribute to hyper link directory
                        AddClassAndStyle(PagingButtonClass, PagingButtonStyle, writer);
                    AddToolTip(writer, index);
                    AddHyperlinkTarget(writer);
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                    if (!string.IsNullOrEmpty(NumericButtonTextFormatString))
                        writer.Write(String.Format(NumericButtonTextFormatString, index));
                    else
                        writer.Write(index);
                    writer.RenderEndTag();
                }
            }
            if ((!isCurrent && PagingButtonLayoutType != PagingButtonLayoutType.None) || (isCurrent && PagingButtonLayoutType == PagingButtonLayoutType.UnorderedList))
                writer.RenderEndTag(); //</li>
        }

        /// <summary>
        /// Create numeric image button.
        /// </summary>
        /// <param name="writer">A <see cref="System.Web.UI.HtmlTextWriter"/> that represents the output stream to render HTML content on the client.</param>
        /// <param name="index">the page index correspond to the button.</param>
        /// <param name="isCurrent">if the page index correspond to the button is the current page index</param>
        private void CreateNumericImages(HtmlTextWriter writer, int index, bool isCurrent)
        {
            AddPagingButtonLayoutTag(writer); //<li> or <span>

            string indexStr = index.ToString();
            for (int i = 0; i < indexStr.Length; i++)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Src, String.Concat(ImagePath, indexStr[i], (isCurrent) ? CpiButtonImageNameExtension : ButtonImageNameExtension, ButtonImageExtension));
                if (ButtonImageAlign != ImageAlign.NotSet)
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, ButtonImageAlign.ToString());
                writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
                writer.RenderBeginTag(HtmlTextWriterTag.Img);
                writer.RenderEndTag();
            }
            if (PagingButtonLayoutType != PagingButtonLayoutType.None)
                writer.RenderEndTag(); //</li> or </span>
        }

        /// <summary>
        /// create more (...) button.
        /// </summary>
        private void CreateMoreButton(HtmlTextWriter writer, int pageIndex)
        {
            if (!ShowMoreButtons)
                return;
            AddClassAndStyle(MoreButtonClass, MoreButtonStyle, writer);
            AddPagingButtonLayoutTag(writer); //<li> or <span>

            writeSpacingStyle(writer);

            writer.AddAttribute(HtmlTextWriterAttribute.Href, GetHrefString(pageIndex));
            AddToolTip(writer, pageIndex);
            AddHyperlinkTarget(writer);
            writer.RenderBeginTag(HtmlTextWriterTag.A); //<a>
            if (PagingButtonType == PagingButtonType.Image && MoreButtonType == PagingButtonType.Image)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Src, String.Concat(ImagePath, "more", ButtonImageNameExtension, ButtonImageExtension));
                writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
                if (ButtonImageAlign != ImageAlign.NotSet)
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, ButtonImageAlign.ToString());
                writer.RenderBeginTag(HtmlTextWriterTag.Img); //<img>
                writer.RenderEndTag(); //</img>
            }
            else
                writer.Write("...");

            writer.RenderEndTag(); //</a>

            if (PagingButtonLayoutType != PagingButtonLayoutType.None)
                writer.RenderEndTag(); //</li> or </span>
        }

        /// <summary>
        /// Add paging button spacing styles to HtmlTextWriter
        /// </summary>
        private void writeSpacingStyle(HtmlTextWriter writer)
        {
            if (PagingButtonSpacing.Value != 0)
            {
                writer.AddStyleAttribute(HtmlTextWriterStyle.MarginRight, PagingButtonSpacing.ToString());
                //writer.AddStyleAttribute(HtmlTextWriterStyle.TextDecoration, "none");
            }
        }

        /// <summary>
        /// add target attribute to paging hyperlink
        /// </summary>
        private void AddHyperlinkTarget(HtmlTextWriter writer)
        {
            if (!string.IsNullOrEmpty(UrlPagingTarget))
                writer.AddAttribute(HtmlTextWriterAttribute.Target, UrlPagingTarget);
        }

        /// <summary>
        /// add css class and style attribute to HtmlTextWriter
        /// </summary>
        private void AddClassAndStyle(string clsname, string style, HtmlTextWriter writer)
        {
            if (!string.IsNullOrEmpty(clsname))
                writer.AddAttribute(HtmlTextWriterAttribute.Class, clsname);
            if (!string.IsNullOrEmpty(style))
                writer.AddAttribute(HtmlTextWriterAttribute.Style, style);
        }


        #endregion

        #region Orerrider

        #region ICallBackable 成员

        [Browsable(true), Category("Behavior"), GlobalizeDescription("IsCallBack"), DefaultValue(true)]
        public bool IsCallBack
        {
            get
            {
                return this.isCallBack;
            }
            set
            {
                this.isCallBack = value;
            }
        }
        [Browsable(true), Category("Behavior"), GlobalizeDescription("CallBackTargets")]
        public string CallBackTargets
        {
            get
            {
                if (this.IsCallBack)
                {
                    return this.displayDuringCallBackTextControls;
                }
                return string.Empty;
            }
            set
            {
                this.displayDuringCallBackTextControls = value;
            }
        }

        #endregion

        protected override void OnPreRender(EventArgs e)
        {
            PageManager.RegisterPageStyleSheet(this, "Pager_css", "CSS/Pager.css");
            this.Page.ClientScript.RegisterClientScriptResource(typeof(Pager), "Water.Resources.Default.JS.Pager.Pager.js");

            base.OnPreRender(e);
            this.IsUpdatedAfterCallBack = true;//is very important
        }

        protected override void RenderContents(HtmlTextWriter writer)
        {
            if (PageCount <= 1 && !AlwaysShow)
                return;
            writer.Indent = 0;
            if (ShowCustomInfoSection != ShowCustomInfoSection.Never)
            {
                if (LayoutType == LayoutType.Table)
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Width, "100%");
                    writer.AddAttribute(HtmlTextWriterAttribute.Style, Style.Value);
                    if (Height != Unit.Empty)
                        writer.AddStyleAttribute(HtmlTextWriterStyle.Height, Height.ToString());
                    writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
                    writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
                    writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
                    writer.RenderBeginTag(HtmlTextWriterTag.Table); //<table>
                    writer.RenderBeginTag(HtmlTextWriterTag.Tr); //<tr>
                }
                if (ShowCustomInfoSection == ShowCustomInfoSection.Left)
                {
                    RenderCustomInfoSection(writer);
                    RenderNavigationSection(writer);
                }
                else
                {
                    RenderNavigationSection(writer);
                    RenderCustomInfoSection(writer);
                }
                if (LayoutType == LayoutType.Table)
                {
                    writer.RenderEndTag(); //</tr>
                    writer.RenderEndTag(); //</table>
                }
            }
            else
                RenderPagingElements(writer);
        }

        public override void RenderEndTag(HtmlTextWriter writer)
        {
            base.RenderEndTag(writer);
            this.dataPager.RenderControl(writer);
        }


        static void addMoreListItem(HtmlTextWriter writer, int pageIndex)
        {
            writer.Write("<option value=\"");
            writer.Write(pageIndex);
            writer.Write("\">......</option>");
        }

        void listPageIndices(HtmlTextWriter writer, int startIndex, int endIndex)
        {
            for (int i = startIndex; i <= endIndex; i++)
            {
                writer.Write("<option value=\"");
                writer.Write(i);
                writer.Write("\"");
                if (i == CurrentPageIndex)
                    writer.Write(" selected=\"true\"");
                writer.Write(">");
                writer.Write(i);
                writer.Write("</option>");
            }
        }
        #endregion

    }




    #region PageChangingEventHandler Delegate

    public delegate void PageChangingEventHandler(object src, PageChangingEventArgs e);

    #endregion

    #region PageChangingEventArgs Class

    public sealed class PageChangingEventArgs : CancelEventArgs
    {
        private readonly int _newpageindex;


        public PageChangingEventArgs(int newPageIndex)
        {
            _newpageindex = newPageIndex;
        }

        public int NewPageIndex
        {
            get { return _newpageindex; }
        }
    }
    #endregion

}
